import { Config, Inject, Provide } from "@midwayjs/core";
import { InjectEntityModel } from "@midwayjs/typeorm";
import { Repository, In } from "typeorm";
import { BblPrizeResult } from "../entity/prize.result.entity";
import { BblPrize } from "../entity/prize.entity";
import { BblPrizeActivity } from "../entity/prize.activity.entity";
import { BblAttach } from "../entity/attach.entity";
import { Utils } from "../utils";
import {
  PrizeResultCreateDto,
  PrizeResultRedeemDto,
  PrizeResultListQueryDto,
  PrizeResultListDto,
  PrizeResultInfoDto,
  BatchGenerateResultDto,
  VerifyLotteryCodeDto,
  PrizeWinnerInfoDto,
  ShippingUpdateDto,
  PrizeGenerateDetail
} from "../dto/prize.result.dto";
import { AttachService } from "./att.service";
import * as fs from "fs";
import * as path from "path";
import * as archiver from "archiver";
import { WxService } from "./wx.service";
import { CosService } from "./cos.service";
import { UploadFileInfo } from "@midwayjs/upload";
import * as xlsx from "xlsx";

/**
 * 抽奖结果服务
 * 提供抽奖码生成、验证、兑奖等功能
 */
@Provide()
export class PrizeResultService {
  @InjectEntityModel(BblPrizeResult)
  resultRepo: Repository<BblPrizeResult>;

  @InjectEntityModel(BblPrize)
  prizeRepo: Repository<BblPrize>;

  @InjectEntityModel(BblPrizeActivity)
  activityRepo: Repository<BblPrizeActivity>;

  @InjectEntityModel(BblAttach)
  attachRepo: Repository<BblAttach>;

  @Inject()
  utils: Utils;

  @Inject()
  cosService: CosService;

  @Inject()
  attachService: AttachService;

  @Inject()
  wxService: WxService;

  @Config("upload.tmpdir")
  tmpdir: string;

  /**
   * 随机生成抽奖码的数量
   */
  @Config("prize.TOTAL_CODES_TO_GENERATE")
  totalGeneratedCodes: number;

  get TOTAL_CODES_TO_GENERATE() {
    return this.totalGeneratedCodes || 20;
  }

  /**
   * 生成随机抽奖码
   * @returns 返回唯一的随机抽奖码
   */
  private generateLotteryCode(): string {
    return this.utils.snowFlake.generate();
  }

  /**
   * 批量生成抽奖码
   * @param dto 抽奖结果创建传输对象
   * @returns 生成结果
   */
  async batchGenerate(dto: PrizeResultCreateDto): Promise<{
    success: boolean;
    data: BatchGenerateResultDto;
    message?: string;
  }> {
    try {
      // 查找活动批次
      const activity = await this.activityRepo.findOne({
        where: { id: dto.activityBatchId }
      });
      if (!activity) {
        return this.utils.service.fail(null, "活动批次不存在");
      }

      // 获取奖品分配映射
      const prizeDistribution = dto.prizeDistribution;
      if (!prizeDistribution || Object.keys(prizeDistribution).length === 0) {
        return this.utils.service.fail(null, "奖品分配映射不能为空");
      }

      // 计算总权重
      const totalWeight = Object.values(prizeDistribution).reduce(
        (sum, weight) => sum + weight,
        0
      );
      if (totalWeight <= 0) {
        return this.utils.service.fail(null, "奖品分配总权重必须大于0");
      }

      // 查找所有相关奖品
      const prizeIds = Object.keys(prizeDistribution);
      const prizes = await this.prizeRepo.find({
        where: { id: In(prizeIds), isDeleted: 0 }
      });

      if (prizes.length !== prizeIds.length) {
        return this.utils.service.fail(null, "部分奖品不存在");
      }

      // 计算每个奖品需要生成的抽奖码数量
      const prizeDetails: PrizeGenerateDetail[] = [];
      let totalAllocated = 0;

      // 按权重排序（从大到小）
      const sortedPrizes = [...prizes].sort(
        (a, b) => prizeDistribution[b.id] - prizeDistribution[a.id]
      );

      // 除了最后一个奖品外，按权重比例分配抽奖码
      for (let i = 0; i < sortedPrizes.length - 1; i++) {
        const prize = sortedPrizes[i];
        const weight = prizeDistribution[prize.id];
        const weightRatio = weight / totalWeight;
        // 计算应分配的数量
        const count = Math.floor(this.TOTAL_CODES_TO_GENERATE * weightRatio);

        prizeDetails.push({
          prizeId: prize.id,
          prizeName: prize.prizeName,
          count,
          weight: weightRatio
        });

        totalAllocated += count;
      }

      // 最后一个奖品分配剩余的所有抽奖码，确保总数正好是TOTAL_CODES_TO_GENERATE
      const lastPrize = sortedPrizes[sortedPrizes.length - 1];
      const remainingCount = this.TOTAL_CODES_TO_GENERATE - totalAllocated;
      const lastPrizeWeight = prizeDistribution[lastPrize.id];
      const lastPrizeWeightRatio = lastPrizeWeight / totalWeight;

      prizeDetails.push({
        prizeId: lastPrize.id,
        prizeName: lastPrize.prizeName,
        count: remainingCount,
        weight: lastPrizeWeightRatio
      });

      // 批量生成抽奖码
      const results: BblPrizeResult[] = [];

      // 按奖品生成抽奖码
      for (const prizeDetail of prizeDetails) {
        const prize = prizes.find((p) => p.id === prizeDetail.prizeId);

        for (let i = 0; i < prizeDetail.count; i++) {
          // 直接使用雪花算法生成唯一抽奖码，无需额外校验
          const uniqueCode = this.generateLotteryCode();

          // 创建抽奖结果记录
          const result = new BblPrizeResult();
          result.id = this.utils.snowFlake.generate();
          result.lotteryCode = uniqueCode;
          result.qrCode = null; // 二维码附件设为空
          result.activityBatch = activity;
          result.prize = prize;
          result.isUsed = 0;
          result.createdBy = "system";

          results.push(result);
        }
      }

      // 批量保存抽奖结果
      await this.resultRepo.save(results);

      this.createResultQrcodes(results, activity);

      // 返回结果
      return this.utils.service.success({
        totalCount: this.TOTAL_CODES_TO_GENERATE,
        activityBatchId: activity.id,
        activityBatchName: activity.batchName,
        details: prizeDetails
      } as BatchGenerateResultDto);
    } catch (error) {
      return this.utils.service.fail(null, `生成抽奖码失败: ${error.message}`);
    }
  }

  /**
   * 为抽奖结果生成二维码
   * @param results 抽奖结果数组
   */
  async createResultQrcodes(
    results: BblPrizeResult[],
    activity: BblPrizeActivity
  ) {
    // 记录成功和失败的结果
    const successResults: BblPrizeResult[] = [];
    const failedResults: BblPrizeResult[] = [];

    // 处理每个抽奖结果
    for (let i = 0; i < results.length; i++) {
      const result = results[i];
      try {
        // 生成二维码，scene传递抽奖码，activity传活动批次id
        const qrCodeResult = await this.getWxAppRewardCode(
          result.lotteryCode,
          result.activityBatch.id
        );

        if (qrCodeResult.success) {
          // 更新抽奖结果的二维码附件
          result.qrCode = qrCodeResult.data;
          successResults.push(result);
        } else {
          // 记录失败信息
          console.log(
            `二维码生成失败: ${result.lotteryCode}, 原因: ${qrCodeResult.message}`
          );
          failedResults.push(result);
        }
      } catch (error) {
        // 记录异常信息
        console.log(
          `二维码生成异常: ${result.lotteryCode}, 原因: ${error.message}`
        );
        failedResults.push(result);
      }
    }

    // 保存成功的结果
    if (successResults.length > 0) {
      await this.resultRepo.save(successResults);
      console.log(`成功处理 ${successResults.length} 个二维码`);
    }

    // 如果有失败的结果，递归处理
    if (failedResults.length > 0) {
      console.log(`有 ${failedResults.length} 个二维码生成失败，准备重试`);
      // 等待一段时间后重试
      await new Promise((resolve) => setTimeout(resolve, 2000));
      // 递归调用处理失败的结果
      await this.createResultQrcodes(failedResults, activity);
    } else {
      // 所有二维码都处理完成，更新批次状态为进行中
      console.log("所有二维码处理完成，准备下载zip包");

      const dirPath = path.join(this.tmpdir, activity.id);
      const zipDir = path.join(process.cwd(), "uploads", "prize-activity");
      if (!fs.existsSync(zipDir)) {
        fs.mkdirSync(zipDir, { recursive: true });
      }
      const zipPath = path.resolve(zipDir, `${activity.batchName}.zip`);

      const output = fs.createWriteStream(zipPath);
      const archive = archiver("zip", { zlib: { level: 9 } });
      archive.pipe(output);
      archive.directory(dirPath, false);
      await archive.finalize();

      // 删除临时文件
      fs.promises.rm(dirPath, { recursive: true, force: true });

      if (results.length > 0) {
        console.log("所有二维码都处理完成，更新批次状态为进行中");
        await this.activityRepo.update(results[0].activityBatch.id, {
          status: 2
        });
      }
    }
  }

  async getWxAppRewardCode(lotteryCode: string, activityBatchId: string) {
    const reuslt = await this.wxService.getWxAppRewardCode(
      lotteryCode,
      activityBatchId
    );
    // console.log("getWxAppRewardCode");
    // console.log(reuslt);
    return reuslt;
  }

  /**
   * 验证抽奖码
   * @param lotteryCode 抽奖码
   * @returns 验证结果
   */
  async verifyLotteryCode(lotteryCode: string): Promise<{
    success: boolean;
    data: VerifyLotteryCodeDto;
    message?: string;
  }> {
    try {
      const result = await this.resultRepo.findOne({
        where: { lotteryCode },
        relations: ["qrCode", "prize", "activityBatch"]
      });

      if (!result) {
        return this.utils.service.fail({
          valid: false,
          message: "抽奖码不存在"
        } as VerifyLotteryCodeDto);
      }

      // 检查活动是否在有效期内
      // const now = new Date();
      // if (
      //   result.activityBatch.startTime > now ||
      //   result.activityBatch.endTime < now
      // ) {
      //   return this.utils.service.success({
      //     valid: false,
      //     message: "活动不在有效期内"
      //   } as VerifyLotteryCodeDto);
      // }

      // 检查抽奖码是否已使用
      if (result.isUsed === 1) {
        return this.utils.service.fail({
          valid: false,
          status: 1,
          message: "抽奖码已使用"
        } as VerifyLotteryCodeDto);
      }

      // 抽奖码有效
      return this.utils.service.success({
        valid: true,
        status: 0,
        result: new PrizeResultInfoDto(result)
      } as VerifyLotteryCodeDto);
    } catch (error) {
      return this.utils.service.fail(null, `验证抽奖码失败: ${error.message}`);
    }
  }

  /**
   * 兑换奖品
   * @param dto 兑奖信息
   * @returns 兑奖结果
   */
  async redeemPrize(dto: PrizeResultRedeemDto): Promise<{
    success: boolean;
    data?: PrizeResultInfoDto;
    message?: string;
  }> {
    try {
      // 验证抽奖码
      const verifyResult = await this.verifyLotteryCode(dto.lotteryCode);
      if (!verifyResult.success || !verifyResult.data.valid) {
        return this.utils.service.fail(
          null,
          verifyResult.data.message || "验证抽奖码失败"
        );
      }

      // 查找抽奖结果记录
      const result = await this.resultRepo.findOne({
        where: { lotteryCode: dto.lotteryCode },
        relations: ["qrCode", "prize", "activityBatch"]
      });

      // 更新兑奖信息
      result.isUsed = 1;
      result.useTime = new Date();
      result.winnerName = dto.winnerName;
      result.contactPhone = dto.contactPhone;
      result.mailingAddress = dto.mailingAddress;
      result.postcode = dto.postcode;
      result.updatedBy = "system";

      // 保存更新
      const updated = await this.resultRepo.save(result);

      return this.utils.service.success(new PrizeResultInfoDto(updated));
    } catch (error) {
      console.log(error);
      return this.utils.service.fail(null, `兑换奖品失败: ${error.message}`);
    }
  }

  /**
   * 获取抽奖结果列表
   * @param query 查询条件
   * @returns 抽奖结果列表
   */
  async list(query: PrizeResultListQueryDto): Promise<{
    success: boolean;
    data: {
      list: PrizeResultListDto[];
    };
    message?: string;
  }> {
    try {
      const qb = this.resultRepo
        .createQueryBuilder("result")
        .leftJoinAndSelect("result.qrCode", "qrCode")
        .leftJoinAndSelect("result.prize", "prize")
        .leftJoinAndSelect("prize.prizeGroup", "prizeGroup")
        .leftJoinAndSelect("result.activityBatch", "activityBatch")
        .leftJoinAndSelect("activityBatch.prizeGroup", "activityPrizeGroup")
        .leftJoinAndSelect("result.trackingAttachment", "trackingAttachment");

      // 应用筛选条件
      if (query.activityBatchId) {
        qb.andWhere("activityBatch.id = :activityBatchId", {
          activityBatchId: query.activityBatchId
        });
      }

      if (query.prizeId) {
        qb.andWhere("prize.id = :prizeId", { prizeId: query.prizeId });
      }

      // 按奖品所属奖品组筛选
      if (query.prizeGroupId) {
        qb.andWhere("prizeGroup.id = :prizeGroupId", {
          prizeGroupId: query.prizeGroupId
        });
      }

      // 按活动批次关联的奖品组筛选
      if (query.activityPrizeGroupId) {
        qb.andWhere("activityPrizeGroup.id = :activityPrizeGroupId", {
          activityPrizeGroupId: query.activityPrizeGroupId
        });
      }

      if (query.lotteryCode) {
        qb.andWhere("result.lotteryCode = :lotteryCode", {
          lotteryCode: query.lotteryCode
        });
      }

      if (query.isUsed !== undefined) {
        qb.andWhere("result.isUsed = :isUsed", { isUsed: query.isUsed });
      }

      if (query.winnerName) {
        qb.andWhere("result.winnerName LIKE :winnerName", {
          winnerName: `%${query.winnerName}%`
        });
      }

      // 排序
      qb.orderBy("result.isUsed", "ASC")
        .addOrderBy("result.useTime", "DESC")
        .addOrderBy("result.createdAt", "DESC");

      // 执行查询
      const results = await qb.getMany();

      // 转换为DTO
      const list = results.map((result) => new PrizeResultListDto(result));

      return this.utils.service.success({ list });
    } catch (error) {
      return this.utils.service.fail(
        null,
        `获取抽奖结果列表失败: ${error.message}`
      );
    }
  }

  /**
   * 分页获取抽奖结果列表
   * @param query 查询条件
   * @param pageSize 每页数量
   * @param current 当前页码
   * @returns 分页抽奖结果列表
   */
  async page(
    query: PrizeResultListQueryDto,
    pageSize: number = 10,
    current: number = 1
  ): Promise<{
    success: boolean;
    data: {
      list: PrizeResultListDto[];
      total: number;
      pageSize: number;
      current: number;
    };
    message?: string;
  }> {
    try {
      const qb = this.resultRepo
        .createQueryBuilder("result")
        .leftJoinAndSelect("result.qrCode", "qrCode")
        .leftJoinAndSelect("result.prize", "prize")
        .leftJoinAndSelect("prize.prizeGroup", "prizeGroup")
        .leftJoinAndSelect("result.activityBatch", "activityBatch")
        .leftJoinAndSelect("activityBatch.prizeGroup", "activityPrizeGroup")
        .leftJoinAndSelect("result.trackingAttachment", "trackingAttachment");

      // 应用筛选条件
      if (query.activityBatchId) {
        qb.andWhere("activityBatch.id = :activityBatchId", {
          activityBatchId: query.activityBatchId
        });
      }

      if (query.prizeId) {
        qb.andWhere("prize.id = :prizeId", { prizeId: query.prizeId });
      }

      // 按奖品所属奖品组筛选
      if (query.prizeGroupId) {
        qb.andWhere("prizeGroup.id = :prizeGroupId", {
          prizeGroupId: query.prizeGroupId
        });
      }

      // 按活动批次关联的奖品组筛选
      if (query.activityPrizeGroupId) {
        qb.andWhere("activityPrizeGroup.id = :activityPrizeGroupId", {
          activityPrizeGroupId: query.activityPrizeGroupId
        });
      }

      if (query.lotteryCode) {
        qb.andWhere("result.lotteryCode = :lotteryCode", {
          lotteryCode: query.lotteryCode
        });
      }

      if (query.isUsed !== undefined) {
        qb.andWhere("result.isUsed = :isUsed", { isUsed: query.isUsed });
      }

      if (query.winnerName) {
        qb.andWhere("result.winnerName LIKE :winnerName", {
          winnerName: `%${query.winnerName}%`
        });
      }

      // 计算总数
      const total = await qb.getCount();

      // 分页查询
      const results = await qb
        .orderBy("result.isUsed", "ASC")
        .addOrderBy("result.useTime", "DESC")
        .addOrderBy("result.createdAt", "DESC")
        .skip((current - 1) * pageSize)
        .take(pageSize)
        .getMany();

      // 转换为DTO
      const list = results.map((result) => new PrizeResultListDto(result));

      return this.utils.service.success({
        list,
        total,
        pageSize,
        current
      });
    } catch (error) {
      return this.utils.service.fail(
        null,
        `分页获取抽奖结果失败: ${error.message}`
      );
    }
  }

  /**
   * 获取已使用抽奖码列表，支持条件筛选
   * @param query 查询条件
   * @returns 已使用抽奖码列表
   */
  async listUsed(query: PrizeResultListQueryDto): Promise<{
    success: boolean;
    data: {
      list: PrizeResultListDto[];
    };
    message?: string;
  }> {
    try {
      const qb = this.resultRepo
        .createQueryBuilder("result")
        .leftJoinAndSelect("result.qrCode", "qrCode")
        .leftJoinAndSelect("result.prize", "prize")
        .leftJoinAndSelect("prize.prizeGroup", "prizeGroup")
        .leftJoinAndSelect("result.activityBatch", "activityBatch")
        .leftJoinAndSelect("activityBatch.prizeGroup", "activityPrizeGroup")
        .leftJoinAndSelect("result.trackingAttachment", "trackingAttachment");

      // 只查询已使用的抽奖码
      qb.andWhere("result.isUsed = :isUsed", { isUsed: 1 });

      // 应用其他筛选条件
      if (query.activityBatchId) {
        qb.andWhere("activityBatch.id = :activityBatchId", {
          activityBatchId: query.activityBatchId
        });
      }
      if (query.prizeId) {
        qb.andWhere("prize.id = :prizeId", { prizeId: query.prizeId });
      }
      if (query.prizeGroupId) {
        qb.andWhere("prizeGroup.id = :prizeGroupId", {
          prizeGroupId: query.prizeGroupId
        });
      }
      if (query.activityPrizeGroupId) {
        qb.andWhere("activityPrizeGroup.id = :activityPrizeGroupId", {
          activityPrizeGroupId: query.activityPrizeGroupId
        });
      }
      if (query.lotteryCode) {
        qb.andWhere("result.lotteryCode = :lotteryCode", {
          lotteryCode: query.lotteryCode
        });
      }
      if (query.winnerName) {
        qb.andWhere("result.winnerName LIKE :winnerName", {
          winnerName: `%${query.winnerName}%`
        });
      }
      if (query.isShipped) {
        qb.andWhere("result.isShipped = :isShipped", {
          isShipped: query.isShipped
        });
      }

      // 排序：已使用时间倒序
      qb.orderBy("result.useTime", "DESC");

      const results = await qb.getMany();
      const list = results.map((result) => new PrizeResultListDto(result));
      return this.utils.service.success({ list });
    } catch (error) {
      return this.utils.service.fail(
        null,
        `获取已使用抽奖码列表失败: ${error.message}`
      );
    }
  }

  /**
   * 分页获取已使用抽奖码列表，按照是否发送奖品排序（未发件排前面）
   * @param query 查询条件
   * @param pageSize 每页数量
   * @param current 当前页码
   * @returns 分页抽奖结果列表
   */
  async pageUsed(
    query: PrizeResultListQueryDto,
    pageSize: number = 10,
    current: number = 1
  ): Promise<{
    success: boolean;
    data: {
      list: PrizeResultListDto[];
      total: number;
      pageSize: number;
      current: number;
    };
    message?: string;
  }> {
    try {
      const qb = this.resultRepo
        .createQueryBuilder("result")
        .leftJoinAndSelect("result.qrCode", "qrCode")
        .leftJoinAndSelect("result.prize", "prize")
        .leftJoinAndSelect("prize.prizeGroup", "prizeGroup")
        .leftJoinAndSelect("result.activityBatch", "activityBatch")
        .leftJoinAndSelect("activityBatch.prizeGroup", "activityPrizeGroup")
        .leftJoinAndSelect("result.trackingAttachment", "trackingAttachment");

      // 只查询已使用的抽奖码
      qb.andWhere("result.isUsed = :isUsed", { isUsed: 1 });

      // 按奖品是否已发送排序
      if (query.isShipped) {
        qb.andWhere("result.isShipped = :isShipped", {
          isShipped: query.isShipped
        });
      }

      // 应用其他筛选条件
      if (query.activityBatchId) {
        qb.andWhere("activityBatch.id = :activityBatchId", {
          activityBatchId: query.activityBatchId
        });
      }

      if (query.prizeId) {
        qb.andWhere("prize.id = :prizeId", { prizeId: query.prizeId });
      }

      // 按奖品所属奖品组筛选
      if (query.prizeGroupId) {
        qb.andWhere("prizeGroup.id = :prizeGroupId", {
          prizeGroupId: query.prizeGroupId
        });
      }

      // 按活动批次关联的奖品组筛选
      if (query.activityPrizeGroupId) {
        qb.andWhere("activityPrizeGroup.id = :activityPrizeGroupId", {
          activityPrizeGroupId: query.activityPrizeGroupId
        });
      }

      if (query.lotteryCode) {
        qb.andWhere("result.lotteryCode = :lotteryCode", {
          lotteryCode: query.lotteryCode
        });
      }

      if (query.winnerName) {
        qb.andWhere("result.winnerName LIKE :winnerName", {
          winnerName: `%${query.winnerName}%`
        });
      }

      // 计算总数
      const total = await qb.getCount();

      // 分页查询，按照是否发送奖品排序（未发件排前面）
      const results = await qb
        .orderBy("result.isShipped", "ASC")
        .addOrderBy("result.useTime", "DESC")
        .skip((current - 1) * pageSize)
        .take(pageSize)
        .getMany();

      // 转换为DTO
      const list = results.map((result) => new PrizeResultListDto(result));

      return this.utils.service.success({
        list,
        total,
        pageSize,
        current
      });
    } catch (error) {
      return this.utils.service.fail(
        null,
        `分页获取已使用抽奖码失败: ${error.message}`
      );
    }
  }

  /**
   * 获取抽奖结果详情
   * @param id 抽奖结果ID
   * @returns 抽奖结果详情
   */
  async info(id: string): Promise<{
    success: boolean;
    data?: PrizeResultInfoDto;
    message?: string;
  }> {
    try {
      const result = await this.resultRepo.findOne({
        where: { id },
        relations: [
          "qrCode",
          "prize",
          "prize.prizeGroup",
          "activityBatch",
          "activityBatch.prizeGroup",
          "trackingAttachment"
        ]
      });

      if (!result) {
        return this.utils.service.fail(null, "抽奖结果不存在");
      }

      return this.utils.service.success(new PrizeResultInfoDto(result));
    } catch (error) {
      return this.utils.service.fail(
        null,
        `获取抽奖结果详情失败: ${error.message}`
      );
    }
  }

  /**
   * 根据抽奖码获取抽奖结果
   * @param lotteryCode 抽奖码
   * @returns 抽奖结果详情
   */
  async getByLotteryCode(lotteryCode: string): Promise<{
    success: boolean;
    data?: PrizeResultInfoDto;
    message?: string;
  }> {
    try {
      const result = await this.resultRepo.findOne({
        where: { lotteryCode },
        relations: [
          "qrCode",
          "prize",
          "prize.prizeImage",
          "prize.prizeGroup",
          "activityBatch",
          "activityBatch.prizeGroup",
          "trackingAttachment"
        ]
      });

      if (!result) {
        return this.utils.service.fail(null, "抽奖码不存在");
      }

      return this.utils.service.success(new PrizeResultInfoDto(result));
    } catch (error) {
      return this.utils.service.fail(null, `查询抽奖码失败: ${error.message}`);
    }
  }

  /**
   * 导出抽奖结果列表
   * @param query 查询条件
   * @returns 抽奖结果列表数据
   */
  async exportList(query: PrizeResultListQueryDto): Promise<{
    success: boolean;
    data?: any[];
    message?: string;
  }> {
    try {
      // 使用list方法获取所有符合条件的数据
      const listResult = await this.list(query);

      if (!listResult.success) {
        return this.utils.service.fail(null, listResult.message);
      }

      // 转换为导出格式
      const exportData = listResult.data.list.map((item) => ({
        抽奖码: item.lotteryCode,
        使用状态: item.isUsedText,
        使用时间: item.useTime ? new Date(item.useTime).toLocaleString() : "",
        兑奖人姓名: item.winnerName || "",
        联系电话: item.contactPhone || "",
        邮寄地址: item.mailingAddress || "",
        邮政编码: item.postcode || "",
        奖品名称: item.prizeName || "",
        活动批次: item.activityBatchName || "",
        创建时间: new Date(item.createdAt).toLocaleString()
      }));

      return this.utils.service.success(exportData);
    } catch (error) {
      return this.utils.service.fail(
        null,
        `导出抽奖结果列表失败: ${error.message}`
      );
    }
  }

  /**
   * 更新兑奖人信息（不进行兑奖）
   * @param dto 兑奖人信息
   * @returns 更新结果
   */
  async updateWinnerInfo(dto: PrizeWinnerInfoDto): Promise<{
    success: boolean;
    data?: PrizeResultInfoDto;
    message?: string;
  }> {
    try {
      // 验证抽奖码
      const verifyResult = await this.verifyLotteryCode(dto.lotteryCode);
      if (!verifyResult.success || !verifyResult.data.valid) {
        return this.utils.service.fail(verifyResult.data, verifyResult.message);
      }

      // 查找抽奖结果记录
      const result = await this.resultRepo.findOne({
        where: { lotteryCode: dto.lotteryCode },
        relations: ["qrCode", "prize", "activityBatch"]
      });

      // 更新兑奖人信息，同时标记为已使用
      result.winnerName = dto.winnerName;
      result.contactPhone = dto.contactPhone;
      result.mailingAddress = dto.mailingAddress;
      result.postcode = dto.postcode;
      result.isUsed = 1; // 标记为已使用
      result.useTime = new Date(); // 设置使用时间为当前时间
      result.updatedBy = "system";

      // 保存更新
      const updated = await this.resultRepo.save(result);

      return this.utils.service.success(new PrizeResultInfoDto(updated));
    } catch (error) {
      return this.utils.service.fail(
        null,
        `更新兑奖人信息失败: ${error.message}`
      );
    }
  }

  /**
   * 更新物流信息
   * @param dto 物流信息更新传输对象
   * @returns 更新结果
   */
  async updateShippingInfo(dto: ShippingUpdateDto): Promise<{
    success: boolean;
    data?: PrizeResultInfoDto;
    message?: string;
  }> {
    try {
      // 查找抽奖结果记录
      const result = await this.resultRepo.findOne({
        where: { id: dto.resultId },
        relations: ["qrCode", "prize", "activityBatch", "trackingAttachment"]
      });

      if (!result) {
        return this.utils.service.fail(null, "抽奖结果不存在");
      }

      // 更新物流信息
      result.isShipped = 1;

      if (dto.shippingCarrier !== undefined) {
        result.shippingCarrier = dto.shippingCarrier;
      }

      if (dto.trackingNumber !== undefined) {
        result.trackingNumber = dto.trackingNumber;
      }

      // 处理快递单号附件
      if (dto.trackingAttachmentId) {
        // 查找附件
        const attachment = await this.attachRepo.findOne({
          where: { attId: dto.trackingAttachmentId }
        });

        if (attachment) {
          result.trackingAttachment = attachment;
        }
      }

      result.updatedBy = "system";

      // 保存更新
      const updated = await this.resultRepo.save(result);

      return this.utils.service.success(new PrizeResultInfoDto(updated));
    } catch (error) {
      return this.utils.service.fail(
        null,
        `更新物流信息失败: ${error.message}`
      );
    }
  }

  /**
   * 批量更新物流信息
   * @param resultIds 抽奖结果ID数组
   * @param dto 物流信息更新传输对象（不包含resultId字段）
   * @returns 更新结果
   */
  async batchUpdateShippingInfo(
    resultIds: string[],
    dto: Omit<ShippingUpdateDto, "resultId">
  ): Promise<{
    success: boolean;
    data: {
      successCount: number;
      failedCount: number;
    };
    message?: string;
  }> {
    try {
      if (!resultIds || resultIds.length === 0) {
        return this.utils.service.fail(null, "请选择需要更新的抽奖结果");
      }

      // 查找所有相关的抽奖结果记录
      const results = await this.resultRepo.findBy({
        id: In(resultIds)
      });

      if (!results || results.length === 0) {
        return this.utils.service.fail(null, "未找到相关的抽奖结果");
      }

      let successCount = 0;
      let failedCount = 0;

      // 如果有附件ID，先查找附件
      let attachment = null;
      if (dto.trackingAttachmentId) {
        attachment = await this.attachRepo.findOne({
          where: { attId: dto.trackingAttachmentId }
        });
      }

      // 批量更新
      for (const result of results) {
        try {
          // 更新物流信息
          result.isShipped = 1;

          if (dto.shippingCarrier !== undefined) {
            result.shippingCarrier = dto.shippingCarrier;
          }

          if (dto.trackingNumber !== undefined) {
            result.trackingNumber = dto.trackingNumber;
          }

          // 设置快递单号附件
          if (attachment) {
            result.trackingAttachment = attachment;
          }

          result.updatedBy = "system";
          successCount++;
        } catch (err) {
          failedCount++;
        }
      }

      // 保存更新
      await this.resultRepo.save(results);

      return this.utils.service.success({
        successCount,
        failedCount
      });
    } catch (error) {
      return this.utils.service.fail(
        null,
        `批量更新物流信息失败: ${error.message}`
      );
    }
  }

  /**
   * excel上传处理过的未发送数据，并存储数据库
   * @param file
   * @returns
   */
  async send_upload(file: UploadFileInfo<any>) {
    // 检查文件名后缀
    const fileName = file.filename;
    const isExcelByExtension = /\.(xlsx?)$/i.test(fileName);

    const mimeType = file.mimeType;
    const excelMimeTypes = [
      "application/vnd.ms-excel",
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    ];
    const isExcelByMimeType = mimeType && excelMimeTypes.includes(mimeType);

    if (!isExcelByExtension && !isExcelByMimeType) {
      return this.utils.service.fail(null, "请上传有效的 Excel 文件。");
    }

    const workbook = xlsx.readFile(file.data.toString());
    const json = xlsx.utils.sheet_to_json(
      workbook.Sheets[workbook.SheetNames[0]]
    );
    const resultList: Array<{
      lotteryCode: string;
      prizeName: string;
      winnerName: string;
      contactPhone: string;
      postcode: string;
      mailingAddress: string;
      isShipped: number;
      shippingCarrier: string;
      trackingNumber: string;
    }> = [];
    json.map((d) => {
      resultList.push({
        lotteryCode: d["编号"],
        prizeName: d["奖品"],
        winnerName: d["兑奖人"],
        contactPhone: d["联系电话"],
        postcode: d["邮编"],
        mailingAddress: d["物流地址"],
        isShipped: d["是否派件"] === "否" ? 0 : 1,
        shippingCarrier: d["物流公司"],
        trackingNumber: d["快递单号"]
      });
    });
    const sended = resultList.filter(
      (d) => d.isShipped === 1 && d.shippingCarrier && d.trackingNumber
    );
    if (sended.length === 0)
      return this.utils.service.fail(
        null,
        "没有需要处理的数据，请将[是否派送]、[物流公司]、[快递单号]填写完整"
      );
    const codeList = sended.map((d) => d.lotteryCode);

    const tList = await this.resultRepo.find({
      where: {
        lotteryCode: In(codeList)
      }
    });

    if (tList.length === 0) {
      return this.utils.service.fail(null, "未找到相关的抽奖结果");
    }

    // 批量更新物流信息
    for (let i = 0; i < tList.length; i++) {
      const target = tList[i];
      const newItem = sended.find((d) => d.lotteryCode === target.lotteryCode);

      target.isShipped = 1;
      target.shippingCarrier = newItem.shippingCarrier;
      target.trackingNumber = newItem.trackingNumber;
    }

    // 保存更新
    await this.resultRepo.save(tList);

    return this.utils.service.success(null);
  }
}
